package workflow

import (
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"shqsoft.cn/pasnj/base"
	"shqsoft.cn/pasnj/popedom"
	"shqsoft.cn/pasnj/workflow/entity"

	"github.com/jinzhu/gorm"
)

//GetExecutor 获取活动的执行人
func GetExecutor(runID int) (userIDs, exclUserIDs []int, err error) {
	flowRun := entity.FlowRun{}
	if err = base.DB.First(&flowRun, runID).Error; err != nil {
		return
	}
	userIDs, exclUserIDs, _, err = getExecutor(base.DB, runID, flowRun.Step, false)
	return
}

func getExecutor(tx *gorm.DB, runID int, step int, verifyAper bool) (userIDs, exclUserIDs []int, descs []string, err error) {
	run := entity.FlowRun{}
	if err = tx.First(&run, runID).Error; err != nil {
		return
	}
	var runSteps []entity.FlowRunStep
	tx.Where(entity.FlowRunStep{RunID: runID, StepID: step}).Order("START_TIME DESC").Find(&runSteps)
	wf := GetWorkFlow(run.WFID)
	if wf == nil {
		err = fmt.Errorf("指定的流程ID:%d在流程配置中不存在！", run.WFID)
		return
	}
	act := wf.GetAction(step)
	if act == nil {
		err = fmt.Errorf("指定的stepID:%d在流程%s配置中不存在！", step, wf.Name)
		return
	}
	userIDs = make([]int, 0, 10)
	exclUserIDs = make([]int, 0, 10)
	descs = make([]string, 0, 10)
	if runSteps == nil || len(runSteps) == 0 || (!verifyAper && run.Step == step && act.Appointer != "") {
		if strings.Index(act.Executor, "@") == 0 {
			userIDs, err = executorPool[act.Executor](tx, runID)
			if err != nil {
				return
			}
			if userIDs != nil {
				count := len(userIDs)
				descs = make([]string, count, count)
			}
			return
		} else if strings.Index(act.Executor, "#") == 0 {
			row := tx.Raw("select EMID from T_FLOW_RUN_STEP where RUNID=? and STEPID=?", runID, act.Executor[1:]).Row()
			var uid int
			err = row.Scan(&uid)
			if err != nil {
				return
			}
			userIDs = append(userIDs, uid)
			descs = append(descs, "")
			return
		}
		orgFromids, err := getOrganFrom(tx, runID, wf, act)
		if err != nil {
			return nil, nil, nil, err
		}
		roleArr := strings.Split(act.Executor, ",")
		cache := base.GetEmployeeCache()
		for _, roleStr := range roleArr {
			roleID, err := strconv.Atoi(roleStr)
			if err != nil {
				return nil, nil, nil, fmt.Errorf("指定的执行人%s错误，必须为int，多个以逗号分开！", act.Executor)
			}
			var idStrs []string
			idStrs, _ = popedom.GetRoleUsersFormRedis(roleID)
			if idStrs == nil || len(idStrs) == 0 {
				role, err := popedom.GetRole(roleID)
				if err != nil {
					return nil, nil, nil, fmt.Errorf("指定的角色ID:%d没有找到！", roleID)
				}
				err = fmt.Errorf("角色%s没有设置人员，请联系管理员设置！", role.RoleName)
				return nil, nil, nil, fmt.Errorf("角色%s没有设置人员，请联系管理员设置！", role.RoleName)
			}
			isExcl := false
			for _, excl := range act.Excludes {
				if excl.ID == roleStr {
					exclFunc, ok := executorExcludePool[excl.Func]
					if ok {
						if canExcl, _ := exclFunc(tx, runID); canExcl {
							isExcl = true
						}
					}
				}
			}
			for _, id := range idStrs {
				userID, err := strconv.Atoi(id)
				if err != nil {
					return nil, nil, nil, err
				}
				oid, poid, err := cache.GetDeptIDByID(userID)
				if err != nil {
					continue
				}
				if len(orgFromids) == 0 && act.OrganFrom == "" {
					if !verifyAper || act.Appointer == "" {
						if !base.IsInSliceForInt(userIDs, userID) {
							userIDs = append(userIDs, userID)
							if isExcl {
								exclUserIDs = append(exclUserIDs, userID)
							}
							descs = append(descs, "")
						}
					}
				} else if act.OrganFrom != "" {
					if base.IsInSliceForInt(orgFromids, oid) || base.IsInSliceForInt(orgFromids, poid) {
						if !base.IsInSliceForInt(userIDs, userID) {
							userIDs = append(userIDs, userID)
							if isExcl {
								exclUserIDs = append(exclUserIDs, userID)
							}
							descs = append(descs, "")
						}
					}
				}
			}
		}
	} else {
		for _, rs := range runSteps {
			if !base.IsInSliceForInt(userIDs, rs.EMID) {
				desc := "待办..."
				if rs.State == "2" {
					desc = rs.Description
					if desc == "" {
						if rs.SubmitTime != nil && rs.SubmitType != "5" && rs.SubmitType != "6" {
							desc = "已办 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "5" {
							desc = "中止 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "6" {
							desc = "待办..."
						} else {
							desc = "待办..."
						}
					}
				} else if rs.State == "3" {
					desc = rs.Description
					if desc == "" {
						if rs.SubmitTime != nil && rs.SubmitType != "5" && rs.SubmitType != "6" {
							desc = "已办 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "5" {
							desc = "中止 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "6" {
							desc = "待办..."
						} else {
							desc = "待办..."
						}
					}
				}
				userIDs = append(userIDs, rs.EMID)
				descs = append(descs, desc)
			}
		}
	}
	return
}

// 查看2021年7月之前的数据
func getExecutorBak(tx *gorm.DB, runID int, step int, verifyAper bool) (userIDs, exclUserIDs []int, descs []string, err error) {
	run := entity.FlowRunBak{}
	if err = tx.First(&run, runID).Error; err != nil {
		return
	}
	var runSteps []entity.FlowRunStepBak
	tx.Where(entity.FlowRunStepBak{RunID: runID, StepID: step}).Order("START_TIME DESC").Find(&runSteps)
	wf := GetWorkFlow(run.WFID)
	if wf == nil {
		err = fmt.Errorf("指定的流程ID:%d在流程配置中不存在！", run.WFID)
		return
	}
	act := wf.GetAction(step)
	if act == nil {
		err = fmt.Errorf("指定的stepID:%d在流程%s配置中不存在！", step, wf.Name)
		return
	}
	userIDs = make([]int, 0, 10)
	exclUserIDs = make([]int, 0, 10)
	descs = make([]string, 0, 10)
	if runSteps == nil || len(runSteps) == 0 || (!verifyAper && run.Step == step && act.Appointer != "") {
		if strings.Index(act.Executor, "@") == 0 {
			userIDs, err = executorPool[act.Executor](tx, runID)
			if err != nil {
				return
			}
			if userIDs != nil {
				count := len(userIDs)
				descs = make([]string, count, count)
			}
			return
		} else if strings.Index(act.Executor, "#") == 0 {
			row := tx.Raw("select EMID from T_FLOW_RUN_STEP_BAK where RUNID=? and STEPID=?", runID, act.Executor[1:]).Row()
			var uid int
			err = row.Scan(&uid)
			if err != nil {
				return
			}
			userIDs = append(userIDs, uid)
			descs = append(descs, "")
			return
		}
		orgFromids, err := getOrganFrom(tx, runID, wf, act)
		if err != nil {
			return nil, nil, nil, err
		}
		roleArr := strings.Split(act.Executor, ",")
		cache := base.GetEmployeeCache()
		for _, roleStr := range roleArr {
			roleID, err := strconv.Atoi(roleStr)
			if err != nil {
				return nil, nil, nil, fmt.Errorf("指定的执行人%s错误，必须为int，多个以逗号分开！", act.Executor)
			}
			var idStrs []string
			idStrs, _ = popedom.GetRoleUsersFormRedis(roleID)
			if idStrs == nil || len(idStrs) == 0 {
				role, err := popedom.GetRole(roleID)
				if err != nil {
					return nil, nil, nil, fmt.Errorf("指定的角色ID:%d没有找到！", roleID)
				}
				err = fmt.Errorf("角色%s没有设置人员，请联系管理员设置！", role.RoleName)
				return nil, nil, nil, fmt.Errorf("角色%s没有设置人员，请联系管理员设置！", role.RoleName)
			}
			isExcl := false
			for _, excl := range act.Excludes {
				if excl.ID == roleStr {
					exclFunc, ok := executorExcludePool[excl.Func]
					if ok {
						if canExcl, _ := exclFunc(tx, runID); canExcl {
							isExcl = true
						}
					}
				}
			}
			for _, id := range idStrs {
				userID, err := strconv.Atoi(id)
				if err != nil {
					return nil, nil, nil, err
				}
				oid, poid, err := cache.GetDeptIDByID(userID)
				if err != nil {
					continue
				}
				if len(orgFromids) == 0 && act.OrganFrom == "" {
					if !verifyAper || act.Appointer == "" {
						if !base.IsInSliceForInt(userIDs, userID) {
							userIDs = append(userIDs, userID)
							if isExcl {
								exclUserIDs = append(exclUserIDs, userID)
							}
							descs = append(descs, "")
						}
					}
				} else if act.OrganFrom != "" {
					if base.IsInSliceForInt(orgFromids, oid) || base.IsInSliceForInt(orgFromids, poid) {
						if !base.IsInSliceForInt(userIDs, userID) {
							userIDs = append(userIDs, userID)
							if isExcl {
								exclUserIDs = append(exclUserIDs, userID)
							}
							descs = append(descs, "")
						}
					}
				}
			}
		}
	} else {
		for _, rs := range runSteps {
			if !base.IsInSliceForInt(userIDs, rs.EMID) {
				desc := "待办..."
				if rs.State == "2" {
					desc = rs.Description
					if desc == "" {
						if rs.SubmitTime != nil && rs.SubmitType != "5" && rs.SubmitType != "6" {
							desc = "已办 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "5" {
							desc = "中止 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "6" {
							desc = "待办..."
						} else {
							desc = "待办..."
						}
					}
				} else if rs.State == "3" {
					desc = rs.Description
					if desc == "" {
						if rs.SubmitTime != nil && rs.SubmitType != "5" && rs.SubmitType != "6" {
							desc = "已办 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "5" {
							desc = "中止 【提交时间：" + rs.SubmitTime.Format("2006-01-02 15:04:05") + "】"
						} else if rs.SubmitTime != nil && rs.SubmitType == "6" {
							desc = "待办..."
						} else {
							desc = "待办..."
						}
					}
				}
				userIDs = append(userIDs, rs.EMID)
				descs = append(descs, desc)
			}
		}
	}
	return
}
func getOrganFrom(tx *gorm.DB, runID int, wf *WorkFlow, act *Action) ([]int, error) {
	if act.OrganFrom == "" {
		return nil, nil
	}
	orgIDs := strings.Split(act.OrganFrom, ",")
	var Vals []string
	if len(orgIDs) == 1 {
		if strings.HasPrefix(orgIDs[0], "SQL:") {
			sqlStr := string(([]byte(act.OrganFrom))[4:])
			rows, err := tx.Raw(sqlStr).Rows()
			if err != nil {
				return nil, err
			}
			defer rows.Close()
			for rows.Next() {
				var val string
				err = rows.Scan(&val)
				if err != nil {
					return nil, err
				}
				Vals = append(Vals, val)
			}
			orgIDs = Vals
		}
	}
	orgIDArr := make([]int, 0, 10)
	for _, orgID := range orgIDs {
		if strings.HasPrefix(orgID, "#") {
			stepStr := string(([]byte(act.OrganFrom))[1:])
			stepID, err := strconv.Atoi(stepStr)
			if err != nil {
				return nil, fmt.Errorf("解析OrganForm:%s错误，必须为INT，多个以逗号隔开！", act.OrganFrom)
			}
			var runSteps []entity.FlowRunStep
			err = tx.Where(entity.FlowRunStep{RunID: runID, StepID: stepID}).Order("START_TIME DESC").Find(&runSteps).Error
			if err != nil {
				return nil, err
			}
			cache := base.GetEmployeeCache()
			for _, runStep := range runSteps {
				oid, poid, err := cache.GetDeptIDByID(runStep.EMID)
				if err != nil {
					return nil, err
				}
				if act.IsSecondLevel {
					if poid == 61 || poid == 80 || poid == 131 {
						orgIDArr = append(orgIDArr, oid)
					} else {
						orgIDArr = append(orgIDArr, oid, poid)
					}
				} else {
					orgIDArr = append(orgIDArr, oid, poid)
				}
			}
		} else if strings.HasPrefix(orgID, "@") {
			colname := string(([]byte(act.OrganFrom))[1:])
			if wf.Entity == "" {
				return nil, fmt.Errorf("流程%s的Entity属性不能为空！", wf.Name)
			}
			dao, err := base.GetDao(wf.Entity)
			if err != nil {
				return nil, err
			}
			objs := dao.GetEntitis()
			err = tx.Where("FRID=?", runID).Find(objs).Error
			if err != nil {
				return nil, err
			}
			values := reflect.ValueOf(objs).Elem()
			if values.Len() == 0 {
				return nil, fmt.Errorf("未找到流程运行ID%d对应的记录", runID)
			}
			field := values.Index(0).FieldByName(colname)
			if field.Kind() == reflect.Ptr {
				field = field.Elem()
			}
			var val interface{}
			if field.IsValid() {
				val = field.Interface()
			}
			if intVal, ok := val.(int); ok {
				orgIDArr = append(orgIDArr, intVal)
				pid, _ := base.GetDepartmentCache().GetPOrgIdByID(intVal)
				if pid > 0 {
					orgIDArr = append(orgIDArr, pid)
				}
			}
		} else {
			oid, err := strconv.Atoi(orgID)
			if err != nil {
				return nil, fmt.Errorf("解析OrganForm:%s错误，必须为INT，多个以逗号隔开！", act.OrganFrom)
			}
			orgIDArr = append(orgIDArr, oid)
		}
	}
	return orgIDArr, nil
}

//SetExecutor 设置指定流程和活动的执行人
func SetExecutor(runID int, step int, userIDs []int) (err error) {
	tx := base.DB.Begin()
	run := entity.FlowRun{}
	if err = tx.First(&run, runID).Error; err != nil {
		return
	}
	if step != run.Step {
		return fmt.Errorf("流程运行不在指定的节点，不能设置执行人！")
	}
	tx.Where(entity.FlowRunStep{RunID: runID, StepID: step}).Delete(entity.FlowRunStep{})
	err = createStep(tx, runID, step, userIDs)
	if err != nil {
		tx.Rollback()
	}
	tx.Commit()
	return
}

func IsManager(permID, userID int) bool {
	for _, wf := range wfContext.WorkFlows {
		if wf.PermID == permID && wf.IsManager(userID) {
			return true
		}
	}
	return false
}
